package com.charles.seckillComponentSecurity.service;

import cn.hutool.core.util.IdUtil;
import com.charles.seckillData.feignService.RemoteLogService;
import com.charles.seckillData.model.UserLogin;
import com.charles.seckillComponentCommon.constants.CacheConstants;
import com.charles.seckillComponentCommon.constants.RoleConstants;
import com.charles.seckillComponentCommon.constants.TokenConstants;
import com.charles.seckillComponentCommon.utils.IpUtils;
import com.charles.seckillComponentCommon.utils.JwtUtils;
import com.charles.seckillComponentRedis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Charles-H
 * 
 * 令牌处理器
 */
@Component
public class TokenService {
    
    @Autowired
    private RedisService redisService;

    @Autowired
    private RemoteLogService remoteLogService;
    
    protected final static long MILLIS_SECOND = 1000;

    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
    
    private final static long EXPIRE_TIME = CacheConstants.EXPIRATION;
    
    private final static String ACCESS_TOKEN = CacheConstants.CACHE_TOKEN;
    
    private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;

    /**
     * 创建令牌
     */
    public Map<String,Object> createToken(UserLogin userLogin) {
        String token = IdUtil.fastUUID();
        Long userId = userLogin.getSysUser().getUser_id();
        String username = userLogin.getSysUser().getUser_name();
        String userCard = userLogin.getSysUser().getUser_card();
        userLogin.setToken(token);
        userLogin.setUserId(userId);
        userLogin.setUsername(username);
        userLogin.setUserCard(userCard);
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        userLogin.setLoginIp(IpUtils.getIpAddr(((ServletRequestAttributes) attributes).getRequest()));
        refreshToken(userLogin);
        
        // 登录日志
        remoteLogService.loginRecord(userLogin, RoleConstants.INNER);
        
        // jwt
        Map<String, Object> map = new HashMap<>();
        map.put(RoleConstants.USER_KYE, token);
        map.put(RoleConstants.USER_ID, userId.toString());
        map.put(RoleConstants.USERNAME, username);
        map.put(RoleConstants.USER_CARD, userCard);

        Map<String, Object> res = new HashMap<>();
        res.put("access_token", JwtUtils.createToken(map));
        res.put("expires_in", EXPIRE_TIME);
        return res;
    }

    /**
     * 刷新令牌
     */
    public void refreshToken(UserLogin userLogin) {
        userLogin.setLoginTime(System.currentTimeMillis());
        userLogin.setExpireTime(userLogin.getLoginTime() + EXPIRE_TIME * MILLIS_MINUTE);
        String tokenKey = getTokenKey(userLogin.getToken());
        redisService.setCacheObject(tokenKey, userLogin, EXPIRE_TIME, TimeUnit.MINUTES);
    }

    /**
     * 获取令牌标识
     */
    public String getTokenKey(String token) {
        return ACCESS_TOKEN + token;
    }

    /**
     * 校验令牌有效期(小于120分钟刷新)
     */
    public void verifyToken(UserLogin userLogin) {
        Long expireTime = userLogin.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) refreshToken(userLogin);
    }

    /**
     * 通过请求获取客户信息
     */
    public UserLogin getUserLogin(HttpServletRequest request) {
        String token = request.getHeader(TokenConstants.TOKEN_AUTHENTICATION);
        if (!token.isEmpty() && token.startsWith(TokenConstants.TOKEN_PREFIX)) {
            token = token.replaceFirst(TokenConstants.TOKEN_PREFIX, "");
        }
        return getUserLogin(token);
    }

    /**
     * 通过令牌获取客户信息
     */
    public UserLogin getUserLogin(String token) {
        try {
            if (!token.isEmpty()) {
                String userKey = JwtUtils.getUserKey(token);
                UserLogin user = redisService.getCacheObject(CacheConstants.CACHE_TOKEN + userKey);
                return user;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 设置客户信息
     */
    public void setUserLogin(UserLogin userLogin) {
        if (userLogin != null && !userLogin.getToken().isEmpty()) refreshToken(userLogin);
    }

    /**
     * 删除客户信息
     */
    public void deleteUserLogin(String token) {
        if (!token.isEmpty()) {
            String userKey = JwtUtils.getUserKey(token);
            redisService.deleteObject(userKey);
        }
    }


}
